﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace H
{
    /// <summary>
    /// 表示一个插件
    /// </summary>
    public abstract class IPlugin
    {
        /// <summary>
        /// 插件表键
        /// </summary>
        public const string HRT_PLUGINDICT = "HRT.PLUGIN_DICT";

        /// <summary>
        /// 获取一个插件实例
        /// </summary>
        /// <param name="pluginName">需要加载的插件的名称</param>
        /// <returns>返回一个插件实例</returns>
        public static IPlugin GetInstance(string pluginName)
        {
            AppDomain.CurrentDomain.Load(pluginName);
            if (AppDomain.CurrentDomain.GetData(HRT_PLUGINDICT) is Dictionary<string, Type> dict)
            {
                if (dict.TryGetValue(pluginName, out Type type))
                {
                    if (Activator.CreateInstance(type) is IPlugin plugin)
                    {
                        return plugin;
                    }
                    else
                    {
                        throw new Exception($"未能成功加载插件[{pluginName}],原因:插件不规范");
                    }
                }
                else
                {
                    throw new Exception($"未能成功加载插件[{pluginName}],原因:无法找到");
                }
            }
            else
            {
                throw new Exception($"未能成功加载插件[{pluginName}],原因:HRT环境损坏");
            }
        }

        /// <summary>
        /// 加载插件并获取目标实例
        /// 此函数为简化创建对象操作,实际上是调用GetInstance()和GetObject()函数,批量创建对象时,建议不要使用此函数
        /// </summary>
        /// <typeparam name="T">插件实例的类型</typeparam>
        /// <param name="pluginName">目标实例</param>
        /// <returns>返回获取到的实例</returns>
        public static T GetObject<T>(string pluginName) where T : class, IFactory
        {
            object obj = GetInstance(pluginName).GetObject();
            return obj as T;
        }

        /// <summary>
        /// 获取插件实例(具体需要传入的参数需要参照手册进行传入)
        /// </summary>
        /// <returns>返回一个插件的实例,需要根据实际情况,</returns>
        public abstract object GetObject();

    }
}
